﻿using System;
using System.Linq;
using MySSH.IDAL;
using NHibernate;
using NHibernate.Criterion;
using NHibernate.Linq;
using Spring.Data.NHibernate.Generic.Support;
using System.Collections.Generic;
using System.Data;
using System.Collections;

namespace MySSH.DAL
{
    public partial class DALBase<T> : HibernateDaoSupport, IDALBase<T> where T : class, new()
    {

        public System.Collections.Generic.IList<T> GetListAll()
        {
            return base.HibernateTemplate.LoadAll<T>();
        }

        public void Delete(T entity)
        {
            base.HibernateTemplate.Delete(entity);
        }

        public T Get(object id)
        {
            return base.HibernateTemplate.Get<T>(id);
        }

        public T Save(T entity)
        {
            base.HibernateTemplate.Save(entity);
            //base.Session.GetIdentifier(entity);
            return entity;
        }

        public void Update(T entity)
        {
            base.HibernateTemplate.Update(entity);
        }

        public void SaveOrUpdate(T entity)
        {
            base.HibernateTemplate.SaveOrUpdate(entity);
        }

        public System.Linq.IQueryable<T> GetQueryByLinq()
        {
            //默认启用缓存Cacheable()
            return base.Session.Query<T>().Cacheable();
        }


        public IQuery GetQueryByHQL(string queryString)
        {
            return base.Session.CreateQuery(queryString).SetCacheable(true);
        }


        public ICriteria GetQueryByCriteria()
        {
            return base.Session.CreateCriteria<T>().SetCacheable(true);
        }


        public ISQLQuery GetQueryBySQL(string queryString)
        {
            return base.Session.CreateSQLQuery(queryString);
        }


        public System.Collections.Generic.IList<T> GetListByPage(int start, int limit, string sort, string dir, out int totalCount, bool isPage, List<ICriterion> criterion)
        {
            ICriteria criteria = this.GetQueryByCriteria();
            // 添加查询条件
            if (criterion != null)
                foreach (var item in criterion)
                    criteria.Add(item);
            //Array.ForEach<ICriterion>(criterion, p => criteria.Add(p));

            //获取记录总数
            ICriteria criteriaRecordCount = CriteriaTransformer.Clone(criteria);
            totalCount = criteriaRecordCount.SetProjection(NHibernate.Criterion.Projections.RowCount()).UniqueResult<int>();

            // 执行分页，主要为考虑导出Excel全部数据的情况
            if (isPage)
                criteria.SetFirstResult(start).SetMaxResults(limit);

            if (!string.IsNullOrEmpty(sort))
                criteria.AddOrder(new Order(sort, "ASC" == dir));

            return criteria.List<T>();
        }


        public T Load(object id)
        {
            return base.HibernateTemplate.Load<T>(id);
        }


        public System.Data.DataSet ExecProc(string procName, out int resutValue, params System.Data.IDataParameter[] param)
        {
            IDbConnection conn = base.Session.Connection;
            IDbCommand cmd = conn.CreateCommand();
            cmd.CommandText = procName;
            cmd.CommandType = CommandType.StoredProcedure;

            IDbDataAdapter da = new System.Data.SqlClient.SqlDataAdapter((System.Data.SqlClient.SqlCommand)cmd);
            if (param == null)
                Array.ForEach<System.Data.IDataParameter>(param, p => cmd.Parameters.Add(p));
            cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("ReturnValue", SqlDbType.Int, 4, ParameterDirection.ReturnValue, false, 0, 0, string.Empty, DataRowVersion.Default, null));
            System.Data.DataSet ds = new DataSet();
            da.Fill(ds);
            resutValue = (int)cmd.Parameters["ReturnValue"];
            return ds;
        }

        public int ExecProc(string procName, params System.Data.IDataParameter[] param)
        {


            IDbConnection conn = base.Session.Connection;
            IDbCommand cmd = conn.CreateCommand();
            cmd.CommandText = procName;
            cmd.CommandType = CommandType.StoredProcedure;

            IDbDataAdapter da = new System.Data.SqlClient.SqlDataAdapter((System.Data.SqlClient.SqlCommand)cmd);
            if (param != null)
                Array.ForEach<System.Data.IDataParameter>(param, p => cmd.Parameters.Add(p));
            IDataParameter resultValueParam = cmd.CreateParameter();
            resultValueParam.DbType = DbType.Int32;
            resultValueParam.Direction = ParameterDirection.ReturnValue;
            resultValueParam.ParameterName = "ReturnValue";
            resultValueParam.SourceVersion = DataRowVersion.Default;
            resultValueParam.SourceColumn = string.Empty;
            //cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("ReturnValue", SqlDbType.Int, 4, ParameterDirection.ReturnValue, false, 0, 0, string.Empty, DataRowVersion.Default, null));
            cmd.ExecuteNonQuery();
            //return (int)cmd.Parameters["ReturnValue"];
            return (int)resultValueParam.Value;
        }



        public System.Collections.IList ExecSQL(string sql)
        {

            IList result = new ArrayList();
            IDbCommand cmd = base.Session.Connection.CreateCommand();
           
            cmd.CommandText = sql;
            IDataReader rs = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            try
            {
                while (rs.Read())
                {
                    int fieldCount = rs.FieldCount;
                    object[] values = new Object[fieldCount];
                    for (int i = 0; i < fieldCount; i++)
                        values[i] = rs.GetValue(i);
                    result.Add(values);
                }
            }
            catch (DataException ex)
            {
                throw ex;
            }
            finally
            {
                //rs.GetSchemaTable()
                if (!rs.IsClosed)
                {
                    rs.Close();
                    rs.Dispose();
                }

            }
            return result;
        }
    }
}
